home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 January: Mac OS SDK / Dev.CD Jan 96 SDK / Dev.CD Jan 96 SDK1.toast / Development Kits (Disc 1) / AOCE / Development Tools / Sample Code / Digital Signatures / Digital Signature Demo / Source ƒ / CSignedObject.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-11  |  6.6 KB  |  333 lines  |  [TEXT/KAHL]

  1. /*
  2.  * CSignedObject.c
  3.  * Copyright © 1993 Apple Computer Inc.
  4.  * All Rights Reserved
  5.  *
  6.  * Extend Digital Signature capability
  7.  * to individual Think Class Library objects.
  8.  */
  9. #include "CSignedObject.h"
  10. #include <CDataFile.h>
  11. #include <Exceptions.h>
  12. #include <OCEErrors.h>
  13.  
  14. /*
  15.  * This is written to, and read from,
  16.  * files by the WriteSignature and
  17.  * ReadSignature methods.
  18.  */
  19. typedef struct SignatureHeader {
  20.     OSType            magicCookie;
  21.     Size            signatureSize;
  22. } SignatureHeader;
  23. /*
  24.  * kMagicCookie is stored in the signature
  25.  * header to help certify that we are actually
  26.  * reading a signature that we wrote.
  27.  */
  28. #define kMagicCookie    gestaltDigitalSignatureVersion
  29.  
  30. void
  31. CSignedObject::ISignedObject(void)
  32. {
  33.         inherited::ISignature();
  34.         itsSignature = NULL;
  35.         itsSignatureSize = 0;
  36. }
  37.  
  38. void
  39. CSignedObject::Dispose(void)
  40. {
  41.         DisposeSignature();
  42.         inherited::Dispose();
  43. }
  44.  
  45. Size
  46. CSignedObject::SignPrepare(
  47.         const FSSpec                *signerFile,
  48.         ConstStr255Param            prompt
  49.     )
  50. {
  51.         itsSignatureSize = inherited::SignPrepare(
  52.                 signerFile,
  53.                 prompt
  54.             );
  55.         return (itsSignatureSize);
  56. }
  57.  
  58. /*
  59.  * Sign creates a signature for the data recently processed
  60.  * by ProcessData. The current signature is used, if it
  61.  * still exists. Sign deletes the context if it fails, but
  62.  * retains it on success so the application can extract
  63.  * certificate information.
  64.  */
  65. void
  66. CSignedObject::Sign(
  67.         SIGStatusProcPtr            statusProc
  68.     )
  69. {
  70.         Boolean                        userCreatedSignature;
  71.         Str255                        msg1;
  72.         Str255                        msg2;
  73.         
  74.         if ((userCreatedSignature = HasSignature()) == FALSE)
  75.             NewSignature();
  76.         if (statusProc == gSIGStatusProc) {
  77.             GetIndString(msg1, STRn_SIGStatusProc, kStatusSignString);
  78.             GetIndString(msg2, STRn_SIGStatusProc, kStatusDataString);
  79.             InitDefaultStatusProc(msg1, msg2);
  80.         }
  81.         TRY {
  82.             FailOSErr(SIGSign(
  83.                     gSIGContextPtr,
  84.                     itsSignature,
  85.                     statusProc
  86.                 ));
  87.         }
  88.         CATCH {
  89.             DisposeDefaultStatusProc();
  90.             if (gLastError != kSIGInvalidCredentialErr) {
  91.                 DisposeSignerContext();
  92.                 if (userCreatedSignature == FALSE)
  93.                     DisposeSignature();
  94.                 DisposeSignerContext();
  95.             }
  96.         }
  97.         ENDTRY;
  98.         DisposeDefaultStatusProc();
  99.         /*
  100.          * It is the caller's responsibility to
  101.          * dispose of the signature and the
  102.          * context as soon as possible.
  103.          */
  104. }
  105.  
  106. /*
  107.  * VerifyPrepare initializes the verification process.
  108.  * The caller must have already loaded the signature into
  109.  * the signature buffer e.g. by reading it from a file.
  110.  * On exit, a context is present.
  111.  */
  112. void
  113. CSignedObject::VerifyPrepare(
  114.         SIGStatusProcPtr            statusProc
  115.     )
  116. {
  117.         OSErr                    status;
  118.         Str255                    msg1;
  119.         Str255                    msg2;
  120.         
  121.         CheckForSignature();
  122.         NewContext(kSIGVerify);
  123.         if (statusProc == gSIGStatusProc) {
  124.             GetIndString(msg1, STRn_SIGStatusProc, kStatusVerifyString);
  125.             GetIndString(msg2, STRn_SIGStatusProc, kStatusDataString);
  126.             InitDefaultStatusProc(msg1, msg2);
  127.         }
  128.         TRY {
  129.             FailOSErr(SIGVerifyPrepare(
  130.                     gSIGContextPtr,
  131.                     itsSignature,
  132.                     itsSignatureSize,
  133.                     statusProc
  134.                 ));
  135.         }
  136.         CATCH {
  137.             if (gLastError != kSIGInvalidCredentialErr) {
  138.                 DisposeDefaultStatusProc();
  139.                 DisposeSignerContext();
  140.             }
  141.         }
  142.         ENDTRY;
  143.         /*
  144.          * Note that a context is present.
  145.          */
  146. }
  147.  
  148. /*
  149.  * Finish verifying an object by checking the result
  150.  * of the ProcessData sequence. This will fail with
  151.  * a paramErr if there is no context. It does not
  152.  * delete the context.
  153.  */
  154. void
  155. CSignedObject::Verify(void)
  156. {
  157.         OSErr                status;
  158.         
  159.         CheckForContext();
  160.         status = SIGVerify(gSIGContextPtr);
  161.         DisposeDefaultStatusProc();
  162.         if (status != noErr
  163.          && status != kSIGInvalidCredentialErr) {
  164.             /*
  165.              * Note: I haven't been able to get this
  166.              * error, so I'm not sure if ws should
  167.              * keep the context if the credentials
  168.              * are "pending or expired."
  169.              */
  170.             DisposeSignerContext();
  171.         }
  172.         FailOSErr(status);
  173. }
  174.  
  175. /*
  176.  * ProcessData is called for all information that is
  177.  * to be signed or verified. Note that it does not
  178.  * move memory. It will fail with a paramErr if
  179.  * there is no context.
  180.  */
  181. void
  182. CSignedObject::ProcessData(
  183.         const void                *data,
  184.         Size                    dataSize
  185.     )
  186. {
  187.         /*
  188.          * While we should call CheckForContext()
  189.          * here, we'll skip it (for speed), hoping
  190.          * that SIGProcessData does the checking
  191.          * or that the error will be caught
  192.          * early in the debugging process.
  193.          */
  194.         FailOSErr(SIGProcessData(
  195.                 gSIGContextPtr,
  196.                 data,
  197.                 dataSize
  198.             ));
  199. }
  200.  
  201. /*
  202.  * Dispose of the current signature. Note that
  203.  * we do not clear the signature size.
  204.  */
  205. void
  206. CSignedObject::DisposeSignature(void)
  207. {
  208.         SIGSignaturePtr                aSignature;
  209.         
  210.         if ((aSignature = itsSignature) != NULL) {
  211.             itsSignature = NULL;
  212.             DisposePtr(aSignature);
  213.             FailMemError();
  214.         }
  215. }
  216.  
  217. /*
  218.  * Return the signature size.
  219.  */
  220. Size
  221. CSignedObject::GetSignatureSize(void)
  222. {
  223.         return (itsSignatureSize);
  224. }
  225.  
  226. /*
  227.  * Create a new signature.
  228.  */
  229. void
  230. CSignedObject::NewSignature(void)
  231. {
  232.         if (itsSignatureSize == 0)
  233.             FailOSErr(paramErr);
  234.         DisposeSignature();
  235.         itsSignature = (SIGSignaturePtr) NewPtr(itsSignatureSize);
  236.         FailNIL(itsSignature);
  237. }
  238.  
  239. /*
  240.  * Return TRUE if there is a current signature.
  241.  */
  242. Boolean
  243. CSignedObject::HasSignature(void)
  244. {
  245.         return (itsSignature != NULL);
  246. }
  247.  
  248. /*
  249.  * Fail if there is no current signature.
  250.  */
  251. void
  252. CSignedObject::CheckForSignature(void)
  253. {
  254.         if (itsSignature == NULL)
  255.             FailOSErr(kSIGNoSignature);
  256. }
  257.  
  258. Size
  259. CSignedObject::CopySignatureToUserBuffer(
  260.         void                *buffer,
  261.         Size                bufferSize
  262.     )
  263. {
  264.         CheckForSignature();
  265.         if (bufferSize < itsSignatureSize)
  266.             FailOSErr(paramErr);
  267.         BlockMove(itsSignature, buffer, itsSignatureSize);
  268.         return (itsSignatureSize);
  269. }
  270.  
  271. void
  272. CSignedObject::MakeSignatureFromUserBuffer(
  273.         void                *buffer,
  274.         Size                bufferSize
  275.     )
  276. {
  277.         DisposeSignature();
  278.         itsSignatureSize = bufferSize;
  279.         NewSignature();
  280.         BlockMove(buffer, itsSignature, bufferSize);
  281. }
  282.  
  283. void
  284. CSignedObject::WriteSignature(
  285.         CDataFile                    *aFile
  286.     )
  287. {
  288.         SignatureHeader        signatureHeader;
  289.         
  290.         signatureHeader.magicCookie = kMagicCookie;
  291.         if (HasSignature() == FALSE)
  292.             signatureHeader.signatureSize = 0;
  293.         else {
  294.             signatureHeader.signatureSize = itsSignatureSize;
  295.         }
  296.         aFile->WriteSome(
  297.                     (Ptr) &signatureHeader,
  298.                     sizeof signatureHeader
  299.                 );
  300.         if (signatureHeader.signatureSize != 0) {
  301.             aFile->WriteSome(
  302.                         itsSignature,
  303.                         signatureHeader.signatureSize
  304.                     );
  305.         }
  306. }
  307.  
  308. void
  309. CSignedObject::ReadSignature(
  310.         CDataFile                    *aFile
  311.     )
  312. {
  313.         SignatureHeader        signatureHeader;
  314.  
  315.         DisposeSignature();
  316.         aFile->ReadSome(
  317.                 (Ptr) &signatureHeader,
  318.                 sizeof signatureHeader
  319.             );
  320.         if (signatureHeader.magicCookie != kMagicCookie)
  321.             FailOSErr(paramErr);
  322.         itsSignatureSize = signatureHeader.signatureSize;
  323.         if (itsSignatureSize > 0) {
  324.             NewSignature();
  325.             aFile->ReadSome(
  326.                 itsSignature,
  327.                 itsSignatureSize
  328.             );
  329.         }
  330. }
  331.  
  332.  
  333.